/*
 * @Author: Swance
 * @Date: 2023-12-28
 * @Description: 自由绘画插件
 */

import { v4 as uuid } from 'uuid';
import { fabric } from 'fabric';
import { IEditor } from '@/types/global';
import { BoardSyncEvent, JsonOption } from '@/utils/Const.ts';

class DrawBrushPlugin {
  canvas: fabric.Canvas;
  editor: IEditor;
  penType: string;
  drawMode: boolean;
  static pluginName = 'DrawBrushPlugin';
  static apis: string[] = [
    'setDrawMode',
    'draw',
    'getDrawMode',
    'setBrushStyle',
    'setBrushColor',
    'setBrushWidth',
  ];

  constructor(canvas: fabric.Canvas, editor: IEditor) {
    this.canvas = canvas;
    this.editor = editor;
    this.penType = 'pencil';
    this.drawMode = false;
    this.init();
  }

  init() {
    const { canvas } = this;
    canvas.on('path:created', (opt) => {
      if (!this.drawMode) return;
      const { path } = opt;
      path.id = uuid();
      path.lock = false;
      path.myType = this.penType;
      path.perPixelTargetFind = true;
      path.strokeUniform = true;
      this.editor.emit(BoardSyncEvent.ADD, {
        isNewAction: true,
        newElements: [path],
      });
    });
  }

  // 设置自由绘画模式
  setDrawMode(params: boolean) {
    this.canvas.isDrawingMode = params;
    this.drawMode = params;
  }
  // 获取自由绘画
  getDrawMode() {
    return this.canvas.isDrawingMode;
  }
  // 笔刷
  draw(type: string, width: number, color: string) {
    this.setDrawMode(true);
    this.penType = type;
    const { canvas } = this;
    canvas.freeDrawingBrush = new fabric.PencilBrush(canvas);
    canvas.freeDrawingBrush.width = width;
    canvas.freeDrawingBrush.color = color;
  }

  getActiveBrushObject() {
    const activeObject = this.canvas.getActiveObject();
    if (
      activeObject &&
      (activeObject.myType === 'pencil' || activeObject.myType === 'markerPen')
    ) {
      return activeObject;
    }
    return null;
  }

  setBrushStyle(type: string) {
    const activeObject = this.getActiveBrushObject();
    if (!activeObject) return;
    const oldElementJson = activeObject.toJSON(JsonOption);
    switch (type) {
      case 'line':
        activeObject.strokeDashArray = [];
        break;
      case 'dash':
        activeObject.strokeDashArray = [25, 35];
        break;
      case 'smallDash':
        activeObject.strokeDashArray = [12, 30];
        break;
    }
    activeObject.dirty = true;
    const newElementJson = activeObject.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }

  setBrushColor(color: string) {
    const activeObject = this.getActiveBrushObject();
    if (!activeObject) return;
    const oldElementJson = activeObject.toJSON(JsonOption);
    activeObject.stroke = color;
    activeObject.dirty = true;
    const newElementJson = activeObject.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }

  setBrushWidth(width: number) {
    const activeObject = this.getActiveBrushObject();
    if (!activeObject) return;
    const oldElementJson = activeObject.toJSON(JsonOption);
    activeObject.strokeWidth = width;
    activeObject.dirty = true;
    const newElementJson = activeObject.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }
}
export default DrawBrushPlugin;
